﻿using UnityEngine;
using System.Collections;
using System.IO;
using System.ComponentModel;

public class Spawner : MonoBehaviour
{
    public bool isEnabled = true;           // run only if true
    public SpriteRenderer backgroundProp;	// The prop to be instantiated.
    public float spawnPosX;				    // The x coordinate of position 
    public float endPosX;                   // the point which the object will be destroyed
    public float minSpawnPosY;				// The lowest possible y coordinate of position.
    public float maxSpawnPosY;				// The highest possible y coordinate of position.
    public float layer;                     // Z factor
    public float minTimeBetweenSpawns;		// The shortest possible time between spawns.
    public float maxTimeBetweenSpawns;		// The longest possible time between spawns.
    public float minSpeed;					// The lowest possible speed of the prop.
    public float maxSpeed;					// The highest possible speed of the prop.
    private float randomSpeed;              // Based on the min/max speed values, used to make objects move on different paces

    public float framesPerSecond;           // Used for sprite animation
    private bool canSpawn = true;           // When true the object will be created
    private float xSpeed;

    public GameObject[] objects;		    // Array of objects prefabs.

    void Start()
    {
        if (!isEnabled)
            return;

        // Set the random seed so it's not the same each game.
        Random.seed = System.DateTime.Now.Millisecond;

        // Initiate the level
        LevelChanged("1");

        // Listen to the level events
        BackgroundManager.OnBeginChange += StartSwitch;
        BackgroundManager.OnChange += LevelChanged;

        // When the main character changes his speed, the background objects should change as well
        PlayerManager.OnSpeedChanged += IncreaseSpeed;

        // Create a random speed, used for objects that want to move with different speed
        randomSpeed = Random.Range(minSpeed, maxSpeed);

        // Make the objects move at the same speed as the player + offset (randomSpeed)
        xSpeed = PlayerManager.getXspeed() + randomSpeed;
    }

    // Start the level change
    private void StartSwitch(string levelIndex)
    {
        // Stop spawning more objects
        canSpawn = false;

        // Assign the new level sprites
        StartCoroutine("LoadSprites", int.Parse(levelIndex));
    }

    // Called when the level is changed
    private void LevelChanged(string levelIndex)
    {
        // Allow spawning
        canSpawn = true;

        // Assign the new level sprites
        StartCoroutine("LoadSprites", int.Parse(levelIndex));

        // Start spawning
        StartCoroutine("Spawn");
    }

    // This method loads all sprites used in the next level
    // Each sprite is loaded on a different update sequence
    IEnumerator LoadSprites(int levelIndex)
    {

            // Return to this point after the next update.
            yield return null;

    }

    // Recursive function which spawns background objects
    IEnumerator Spawn()
    {

        // Create a random wait time before the prop is instantiated.
        float waitTime = Random.Range(minTimeBetweenSpawns, maxTimeBetweenSpawns);

        // Wait for the designated period.
        yield return new WaitForSeconds(waitTime);
        
        // Create a random y coordinate for the prop.
        float posY = Random.Range(minSpawnPosY, maxSpawnPosY);

        // Set the position the prop should spawn at.
        Vector3 spawnPos = new Vector3(spawnPosX, posY, layer);

        // Instantiate a random enemy.
        int objectIndex = Random.Range(0, objects.Length - 1);
        print(objects.Length);
        print(objectIndex);
        // Instantiate the prop at the desired position.
        SpriteRenderer propInstance = Instantiate(objects[objectIndex], spawnPos, Quaternion.identity) as SpriteRenderer;

        print(canSpawn);
        // Restart the coroutine to spawn another prop.
        if (canSpawn)
        {
            //DebugStreamer.messages.Add( "canSpawn = true");
            StartCoroutine(Spawn());
        }

        // While the prop exists...
        while (propInstance != null)
        {
            //cyclePNGAnimation(propInstance, animationIndex);
            propInstance.transform.position += Vector3.right * xSpeed * Time.deltaTime;

            // Otherwise, if the prop is facing right and it's beyond the right spawn position...
            if (propInstance.transform.position.x > endPosX + 0.5f)
            {
                // ... destroy the prop.
                Destroy(propInstance.gameObject);
                Destroy(propInstance);
            }

            // Return to this point after the next update.
            yield return null;
        }
    }

    private void IncreaseSpeed(float newSpeed)
    {
        xSpeed = newSpeed + randomSpeed;
    }

    private void cyclePNGAnimation(SpriteRenderer propInstance, int animationIndex)
    {
        //int index = (int)(Time.timeSinceLevelLoad * framesPerSecond);
        //index = index % sprites[animationIndex].Length;
        //propInstance.sprite = sprites[animationIndex][index];
    }

}
